import allure
from pymysql import Connection
from VAR.VAR import DATABASE
from loguru import logger


class SqlCursor:
    """sql游标类"""
    # 获取连接mysql服务的配置信息
    __host = DATABASE["MYSQL"]["IP"]
    __username = DATABASE["MYSQL"]["USERNAME"]
    __password = DATABASE["MYSQL"]["PASSWORD"]
    __port = DATABASE["MYSQL"]["PORT"]
    __database = DATABASE["MYSQL"]["DATABASE"]

    __database_obj = None

    @classmethod
    @allure.step("获取数据库连接对象.....")
    def __get_connect(cls):
        """
        采用单例模式获取数据库连接对象
        :return: 数据库连接对象
        """
        if not cls.__database_obj:
            # 连接配置的数据库
            cls.__database_obj = Connection(host=cls.__host, port=cls.__port,
                                            user=cls.__username, password=cls.__password,
                                            db=cls.__database, charset='utf8')
            return cls.__database_obj
        else:
            return cls.__database_obj

    @classmethod
    @allure.step("关闭数据库连接对象......")
    def __close_database_obj(cls):
        """
        关闭数据库连接【不为空才可关闭，关闭后重置为None】
        """
        if cls.__database_obj:
            cls.__database_obj.close()
            cls.__database_obj = None

    @classmethod
    @allure.step("正在进行DML操作......")
    def execute_sql_dml(cls, sql):
        """
        根据sql执行增删改sql语句
        :param sql: 增删改的sql语句
        :return: 受影响的行数
        """
        cursor = None
        try:
            # 获取游标对象
            cursor = cls.__get_connect().cursor()
            # 执行sql
            cursor.execute(sql)
            # 提交事务
            cls.__database_obj.commit()
            # 受影响的行数
            count = cursor.rowcount
        except Exception as ex:
            allure.attach(f"执行DML操作发生异常: {ex}......")
            raise ex
        finally:
            # 关闭连接
            cursor.close()
            cls.__close_database_obj()
        return count

    @classmethod
    @allure.step("正在进行DQL操作.....")
    def execute_sql_dql(cls, sql):
        """
        根据sql执行查询sql语句
        :param sql: 查询sql语句
        :return: 查询到的结果集 以二维元组的形式返回
        """
        cursor = None
        try:
            # 获取游标对象
            cursor = cls.__get_connect().cursor()
            # 执行sql
            cursor.execute(sql)
            # 查询结果
            result = cursor.fetchall()
        except Exception as ex:
            allure.attach(f"执行DQL操作发生异常: {ex}......")
            # 详细记录sql_cursor相关异常信息到日志
            # logger.error(f"在执行数据库查询操作（sql_cursor.execute_sql_dql）时发生异常, "
            #              f"异常类型: {type(ex).__name__}, ")
            raise ex
        finally:
            # 关闭连接
            cursor.close()
            cls.__close_database_obj()
        return result
